﻿using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Xml.Serialization;

namespace 剧情设计器2._0
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        //刷新treeview的显示
        public void UpdateDisplay()
        {
            List<string> newcharacters = new List<string>();
            treeView.BeginUpdate();
            treeView.Nodes.Clear();
            //设置根节点
            treeView.Nodes.Add(new TreeNode() { Text = Common.story.name });
            TreeNode node_story = treeView.Nodes[0];
            //遍历故事，逐层创建剧情树
            foreach(Node node in Common.story.nodes)
            {
                TreeNode node_node = new TreeNode() { Text = node.name };
                foreach(Plot plot in node.plots)
                {
                    TreeNode node_plot = new TreeNode() { Text = plot.name };
                    foreach(Event @event in plot.events)
                    {
                        TreeNode node_event = new TreeNode() { Text = @event.name };
                        foreach(Action action in @event.actions)
                        {
                            TreeNode node_action = new TreeNode() { Text = "动作" };
                            TreeNode node_emitter = new TreeNode() { Text = string.Format("发出者: {0}", action.emitter) };
                            TreeNode node_receiver = new TreeNode() { Text = string.Format("接受者: {0}", action.receiver) };
                            TreeNode node_actiontype = new TreeNode() { Text = string.Format("类型: {0}", action.type) };
                            TreeNode node_detail = new TreeNode() { Text = string.Format("动作描述: {0}", action.description) };


                            if (!Common.inCharacters(action.emitter) && action.emitter != "" && !Common.inList(action.emitter, newcharacters)) newcharacters.Add(action.emitter);
                            if (!Common.inCharacters(action.receiver) && action.receiver != "" && !Common.inList(action.receiver, newcharacters)) newcharacters.Add(action.receiver);
                            
                            node_action.Nodes.Add(node_emitter);
                            node_action.Nodes.Add(node_receiver);
                            node_action.Nodes.Add(node_actiontype);
                            node_action.Nodes.Add(node_detail);
                            
                            //先判断一下有没有关系变动，如果没有的话，就不显示了
                            if(action.relationships.Count != 0)
                            {
                                TreeNode node_relationship_changed = new TreeNode() { Text = "关系变动" };
                                foreach (Relationship relationship in action.relationships)
                                {
                                    TreeNode node_relationship = new TreeNode()
                                    {
                                        Text = string.Format("[{0}] {1}--{2}-->{3}", relationship.build ? "建立" : "删除", relationship.active_character, relationship.relationship, relationship.passive_character)
                                       
                                    };
                                    if (!Common.inCharacters(relationship.active_character) && relationship.active_character != "" && !Common.inList(relationship.active_character, newcharacters)) newcharacters.Add(relationship.active_character);
                                    if (!Common.inCharacters(relationship.passive_character) && relationship.passive_character != "" && !Common.inList(relationship.passive_character, newcharacters)) newcharacters.Add(relationship.passive_character);
                                    node_relationship_changed.Nodes.Add(node_relationship);
                                }
                                node_action.Nodes.Add(node_relationship_changed);
                            }
                            node_event.Nodes.Add(node_action);
                        }
                        node_plot.Nodes.Add(node_event);
                    }
                    node_node.Nodes.Add(node_plot);
                }
                node_story.Nodes.Add(node_node);
            }

            if(newcharacters.Count != 0)
            {
                ConfirmNewCharacterDialog dlg = new ConfirmNewCharacterDialog(newcharacters);
                dlg.Show();
            }

            foreach(string newname in newcharacters)
            {
                Common.characters.Add(new Character() { name = newname });
            }
            
            treeView.EndUpdate();
            treeView.ExpandAll();
            updateRelationshipTable();
            
        }

        private void CharactersManagerClick(object sender, EventArgs e)
        {
            CharactersManager cm = new CharactersManager();
            cm.Show();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Common.story.name = "新故事";
            UpdateDisplay();
            Common.last = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.action_types.GetHashCode(), Common.relationship_types.GetHashCode(), Common.setting_types.GetHashCode());
        }

        private void editStoryName(object sender, EventArgs e)
        {
            string newname = Interaction.InputBox("请输入故事名：", "编辑故事名", Common.story.name);
            
            if(newname == "")
            {
                MessageBox.Show("故事名不能为空", "编辑故事名", MessageBoxButtons.OK);
                return;
            }
            Common.story.name = newname;
            UpdateDisplay();
        }

        //创建节点被点击
        private void CreateNodeClick(object sender, EventArgs e)
        {
            Node node = new Node() { name = "新节点" };
            Common.story.nodes.Add(node);
            UpdateDisplay();
            NodeEditor ne = new NodeEditor(node);
            ne.Show();
            UpdateDisplay();
        }

        //这个函数负责响应treeview节点被双击的事件
        //节点被双击后，应该打开对于的编辑器
        private void treeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (treeView.SelectedNode == null) return;

            int level = treeView.SelectedNode.Level;
            //MessageBox.Show(e.Node.Level.ToString());
            TreeNode node = treeView.SelectedNode;
            int idx = node.Index;
            switch (level)
            {
                case Common.Level.Story:
                    editStoryName(sender, new EventArgs());
                    break;

                case Common.Level.Node:
                    NodeEditor ne = new NodeEditor(Common.story.nodes[idx]);
                    ne.Show();
                    break;

                case Common.Level.Plot:
                    PlotEditor pe = new PlotEditor(Common.story.nodes[node.Parent.Index].plots[idx]);
                    pe.Show();
                    break;

                case Common.Level.Event:
                    EventEditor ee = new EventEditor(Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx]);
                    ee.Show();
                    break;
                case Common.Level.Action:
                    ActionEditor ae = new ActionEditor(
                        Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx]
                        );
                    ae.Show();
                    break;
            }
            UpdateDisplay();
        }

        //更新关系表
        public void updateRelationshipTable()
        {
            //=========================初始化关系表==========================================
            //这里先把关系表初始化为空
            Common.relationshipTable = new Dictionary<string, Dictionary<string, List<string>>>();
            //这里两次循环初始化的目的是让关系表中的任意两个人之间存在空关系列表，以免出现keyerror
            //也就是说，要让两个字典的keys里有每个角色的名字
            foreach (Character c in Common.characters)
            {
                Common.relationshipTable[c.name] = new Dictionary<string, List<string>>();
            }
            foreach (Character c1 in Common.characters)
            {
                foreach (Character c2 in Common.characters)
                {
                    Common.relationshipTable[c1.name][c2.name] = new List<string>();
                }
            }
            //==========================初始化结束=========================================
            //遍历所有的关系变化
            foreach (Node node in Common.story.nodes)
            {
                foreach (Plot plot in node.plots)
                {
                    foreach (Event @event in plot.events)
                    {
                        foreach (Action action in @event.actions)
                        {
                            foreach (Relationship relationship in action.relationships)
                            {
                                //如果是建立关系
                                if (relationship.build)
                                {
                                    //首先要判断关系是否存在于这两个人之间，如果存在，就不再添加
                                    if (!Common.inList(relationship.relationship, Common.relationshipTable[relationship.active_character][relationship.passive_character]))
                                    {
                                        Common.relationshipTable[relationship.active_character][relationship.passive_character].Add(relationship.relationship);
                                    }
                                }
                                //如果是删除关系
                                else
                                {
                                    //同理，先判断是否存在，不存在的话不能删除
                                    if (!Common.inList(relationship.relationship, Common.relationshipTable[relationship.active_character][relationship.passive_character]))
                                    {
                                        Common.relationshipTable[relationship.active_character][relationship.passive_character].Remove(relationship.relationship);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void ShowRelationshipTableClick(object sender, EventArgs e)
        {
            RelationshipTable rt = new RelationshipTable();
            rt.Show();
        }

        private void RelationshipTypesManagerClick(object sender, EventArgs e)
        {
            (new RelationshipTypesManager()).Show();
        }

        private void ActionTypesManagerClick(object sender, EventArgs e)
        {
            (new ActionTypesManager()).Show();
        }

        private void SettingTypesManagerClick(object sender, EventArgs e)
        {
            (new SettingTypesManager()).Show();
        }

        //保存文件函数
        public void saveFile()
        {
            //第一个文件，.plt文件，负责保存剧情树
            FileStream fs_mainfile = new FileStream(Common.filepath, FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xmlSerializer_mainfile = new XmlSerializer(typeof(Story));
            xmlSerializer_mainfile.Serialize(fs_mainfile, Common.story);
            fs_mainfile.Close();

            //第二个文件，.character文件，负责保存角色设定
            FileStream fs_characters = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".characters", FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xmlSerializer_characters = new XmlSerializer(typeof(List<Character>));
            xmlSerializer_characters.Serialize(fs_characters, Common.characters);
            fs_characters.Close();

            //第三个文件，.settingtypes文件，负责保存设定类型
            FileStream fs_settings = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".settingtypes", FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xmlSerializer_settings = new XmlSerializer(typeof(List<string>));
            xmlSerializer_settings.Serialize(fs_settings, Common.setting_types);
            fs_settings.Close();

            //第四个文件，.relationshiptypes文件，负责保存关系类型
            FileStream fs_relationshiptypes = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".relationshiptypes", FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xmlSerializer_relationshiptypes = new XmlSerializer(typeof(List<string>));
            xmlSerializer_relationshiptypes.Serialize(fs_relationshiptypes, Common.relationship_types);
            fs_relationshiptypes.Close();

            //第五个文件，.actiontypes文件，负责保存动作类型
            FileStream fs_actiontypes = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".actiontypes", FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xmlSerializer_actiontypes = new XmlSerializer(typeof(List<string>));
            xmlSerializer_actiontypes.Serialize(fs_actiontypes, Common.action_types);
            fs_actiontypes.Close();
        }

        private void SaveFileClick(object sender, EventArgs e)
        {
            if(Common.filepath != "" && Common.filepath != null)
            {
                backupFile();
                saveFile();
                Common.last = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.getStringLishHash(Common.action_types), Common.getStringLishHash(Common.relationship_types), Common.getStringLishHash(Common.setting_types));
            }
            else
            {
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    Common.filepath = saveFileDialog.FileName;
                    Common.updateTitle();
                    backupFile();
                    saveFile();
                    Common.last = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.getStringLishHash(Common.action_types), Common.getStringLishHash(Common.relationship_types), Common.getStringLishHash(Common.setting_types));
                }
            }
        }

        //读取文件
        private void openFileClick(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                Common.filepath = openFileDialog.FileName;
                Common.updateTitle();
            }
            else return;

            try
            {
                FileStream fs_mainfile = new FileStream(Common.filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(Story));
                Common.story = (Story)xmlSerializer.Deserialize(fs_mainfile);
                fs_mainfile.Close();

                FileStream fs_characters = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".characters", FileMode.Open, FileAccess.Read, FileShare.Read);
                XmlSerializer xmlSerializer2 = new XmlSerializer(typeof(List<Character>));
                Common.characters = (List<Character>)xmlSerializer2.Deserialize(fs_characters);
                fs_characters.Close();

                FileStream fs_settings = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".settingtypes", FileMode.Open, FileAccess.Read, FileShare.Read);
                XmlSerializer xmlSerializer3 = new XmlSerializer(typeof(List<string>));
                Common.setting_types = (List<string>)xmlSerializer3.Deserialize(fs_settings);
                fs_settings.Close();

                FileStream fs_relationshiptypes = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".relationshiptypes", FileMode.Open, FileAccess.Read, FileShare.Read);
                XmlSerializer xmlSerializer4 = new XmlSerializer(typeof(List<string>));
                Common.relationship_types = (List<string>)xmlSerializer4.Deserialize(fs_relationshiptypes);
                fs_relationshiptypes.Close();

                FileStream fs_actiontypes = new FileStream(Common.filepath.Substring(0, Common.filepath.Length - 4) + ".actiontypes", FileMode.Open, FileAccess.Read, FileShare.Read);
                XmlSerializer xmlSerializer5 = new XmlSerializer(typeof(List<string>));
                Common.action_types = (List<string>)xmlSerializer5.Deserialize(fs_actiontypes);
                fs_actiontypes.Close();
            }
            catch
            {

            }
            

            UpdateDisplay();
            Common.last = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.action_types.GetHashCode(), Common.relationship_types.GetHashCode(), Common.setting_types.GetHashCode());
            //MessageBox.Show(Common.last.GetHashCode().ToString());
        }

        private void SaveAsClick(object sender, EventArgs e)
        {
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                Common.filepath = saveFileDialog.FileName;
                Common.updateTitle();
            }
            else return;
            backupFile();
            saveFile();
            Common.last = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.getStringLishHash(Common.action_types), Common.getStringLishHash(Common.relationship_types), Common.getStringLishHash(Common.setting_types));
        }

        private void DeleteClick(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node == null) return;
            int level = treeView.SelectedNode.Level;
            switch (level)
            {
                case Common.Level.Story:
                    MessageBox.Show("故事根节点不能被删除!", "删除", MessageBoxButtons.OK);
                    return;
                case Common.Level.Node:
                    if(MessageBox.Show(string.Format("确定要删除节点 {0} 吗？", Common.story.nodes[node.Index].name), "删除", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        Common.story.nodes.RemoveAt(node.Index);
                        UpdateDisplay();
                    }
                    break;
            }
        }

        private void editStorySummaryClick(object sender, EventArgs e)
        {
            SummaryEditor se = new SummaryEditor();
            se.Show();
        }

        private void editWorldSettingClick(object sender, EventArgs e)
        {
            (new WorldSettingEditor()).Show();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            var cur = new ValueTuple<int, int, int, int>(Common.story.GetHashCode(), Common.getStringLishHash(Common.action_types), Common.getStringLishHash(Common.relationship_types), Common.getStringLishHash(Common.setting_types));
            //MessageBox.Show(string.Format("{0} {1}", Common.last.ToString(), cur.ToString()));
            if(Common.VisualViewOpened)
            {
                Common.vv.Close();
            }
            if (!Common.last.Equals(cur))
            {
                DialogResult dr = MessageBox.Show("当前修改的内容未保存，是否在关闭前保存文件？", "关闭窗口", MessageBoxButtons.YesNoCancel);
                if (dr == DialogResult.Cancel)
                {
                    e.Cancel = true;
                }
                else if (dr == DialogResult.Yes)
                {
                    backupFile();
                    SaveFileClick(sender, new EventArgs());
                    e.Cancel = false;
                }
                else
                {
                    e.Cancel = false;
                }
            }
        }

        private void timer_savefile_Tick(object sender, EventArgs e)
        {
            if (Common.filepath != "") 
            {
                backupFile();
                saveFile();
            }
            message.Text = "自动保存文件于 " + DateTime.Now.ToString();
        }

        void backupFile()
        {
            if (Common.filepath == "" || Common.filepath == null) return;
            string root = Common.filepath.Substring(0, Common.filepath.Length - 4);
            try
            {
                System.IO.File.Copy(root + ".plt", root + ".plt.backup");
                System.IO.File.Copy(root + ".characters", root + ".characters.backup");
                System.IO.File.Copy(root + ".settingtypes", root + ".settingtypes.backup");
                System.IO.File.Copy(root + ".relationshiptypes", root + ".relationshiptypes.backup");
                System.IO.File.Copy(root + ".actiontypes", root + ".actiontypes.backup");
            }
            catch
            {

            }
        }

        private void statusStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }



        private void MoveUpClick(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node == null) return;
            int idx = node.Index;
            if (idx == 0) return;
            switch(node.Level)
            {
                case Common.Level.Node:
                    var temp = Common.story.nodes[idx];
                    Common.story.nodes[idx] = Common.story.nodes[idx - 1];
                    Common.story.nodes[idx - 1] = temp;
                    break;
                case Common.Level.Plot:
                    var temp2 = Common.story.nodes[node.Parent.Index].plots[idx];
                    Common.story.nodes[node.Parent.Index].plots[idx] = Common.story.nodes[node.Parent.Index].plots[idx - 1];
                    Common.story.nodes[node.Parent.Index].plots[idx - 1] = temp2;
                    break;

                case Common.Level.Event:
                    var temp3 = Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx];
                    Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx] = Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx - 1];
                    Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx - 1] = temp3;
                    break;
                case Common.Level.Action:
                    var temp4 = Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx];
                    Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx] = Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx - 1];
                    Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx - 1] = temp4;
                    break;
                default:
                    MessageBox.Show("该节点不能被移动!", "移动节点");
                    break;
            }
            UpdateDisplay();
        }

        private void MoveDownClick(object sender, EventArgs e)
        {
            TreeNode node = treeView.SelectedNode;
            if (node == null) return;
            int idx = node.Index;
            switch (node.Level)
            {
                case Common.Level.Node:
                    if (idx == Common.story.nodes.Count) return;
                    var temp = Common.story.nodes[idx];
                    Common.story.nodes[idx] = Common.story.nodes[idx + 1];
                    Common.story.nodes[idx + 1] = temp;
                    break;
                case Common.Level.Plot:
                    if (idx == Common.story.nodes[node.Parent.Index].plots.Count) return;
                    var temp2 = Common.story.nodes[node.Parent.Index].plots[idx];
                    Common.story.nodes[node.Parent.Index].plots[idx] = Common.story.nodes[node.Parent.Index].plots[idx + 1];
                    Common.story.nodes[node.Parent.Index].plots[idx + 1] = temp2;
                    break;

                case Common.Level.Event:
                    if (idx == Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events.Count) return;
                    var temp3 = Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx];
                    Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx] = Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx + 1];
                    Common.story.nodes[node.Parent.Parent.Index].plots[node.Parent.Index].events[idx + 1] = temp3;
                    break;
                case Common.Level.Action:
                    if (idx == Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions.Count) return;
                    var temp4 = Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx];
                    Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx] = Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx + 1];
                    Common.story.nodes[node.Parent.Parent.Parent.Index].plots[node.Parent.Parent.Index].events[node.Parent.Index].actions[idx + 1] = temp4;
                    break;
                default:
                    MessageBox.Show("该节点不能被移动!", "移动节点");
                    break;
            }
            UpdateDisplay();
        }

        private void ShowVisualView(object sender, EventArgs e)
        {
            if(!Common.VisualViewOpened)
            {
                Common.vv = new VisualView();
                Common.VisualViewOpened = true;
                Common.vv.Show();
            }
        }
    }
}
